How to Install Docker on Debian 12 Step by Step

Pantalla de terminal con comandos de instalación en Linux

Installing Docker on Debian 12 looks like a mechanical errand — you copy four commands from the official docs and you are done — but hidden inside that process are decisions that shape the next twelve months of operation. Which repository to use, which packages to pick, how to manage permissions, and what to put into daemon.json from the very first boot are questions with real consequences when the machine graduates from personal experiment to exposed service. This guide walks through the install on Debian 12 (Bookworm) explaining the why behind each step, not only the what.

Why Not the Debian Package

Debian ships docker.io in its repositories, and for tinkering on a laptop that is fine. Once the machine does real work, the distribution package falls short: the packaged version trails Docker’s stable branch by several minors, security patches take longer to land, and the related components — engine, CLI, containerd, BuildKit — are not updated as a coordinated set. Sooner or later you end up hand-patching something or living with a bug that was already fixed upstream.

Docker’s official repository solves those three problems at once. You receive the current version, patches arrive the day they are released, and components move together as a coherent bundle. On top of that the docker compose v2 plugin comes packaged alongside the engine, ending the historical dance between hyphenated docker-compose and space-separated docker compose. For any server destined for production use, the choice is clear: official repository from the start.

Preparing the Ground

Before adding anything new, clear out any previous install. If the machine ever ran docker.io, docker-engine, or a stray runc, those packages will conflict with the official ones. An apt-get remove of docker docker-engine docker.io containerd runc cleans the binaries without touching the images or volumes under /var/lib/docker and /var/lib/containerd. Those directories hold data that does not regenerate itself, so think twice before deleting them.

With the system clean, refresh APT and install the minimum dependencies needed to add a signed repository: ca-certificates, curl, and gnupg.

GPG Key and Repository

Debian’s modern method for adding repository keys is to drop them into /etc/apt/keyrings/ as individual files. The old apt-key add has been flagged deprecated for years for a valid reason: a globally installed key implicitly signs any repository, breaking the isolation APT tries to offer. The current approach is to download Docker’s key, convert it with gpg --dearmor, and save it into that dedicated directory.

Next you add the repository line in /etc/apt/sources.list.d/docker.list, referencing the key by absolute path via the signed-by= option. That directive is what makes the key exclusive to that repo — APT will only accept Docker signatures for packages from download.docker.com. The recommended snippet resolves architecture and codename automatically, so the same command works on amd64 and arm64 and survives the next Debian upgrade untouched.

Installing the Right Packages

Docker is not a single binary but a collection of pieces with distinct jobs, and it pays to understand what each one does before pasting the apt-get install. The standard install requires five packages:

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

docker-ce is the dockerd daemon listening on the Unix socket and orchestrating containers. docker-ce-cli is the client, the docker command that talks to the daemon through that socket. containerd.io is the low-level runtime that actually launches containers — Docker has delegated to it for years. The two remaining plugins add multi-platform builds with BuildKit and the declarative v2 orchestrator. After the install, systemd starts the service and leaves it enabled.

Verification and the docker Group

Three commands confirm everything is in place: docker --version prints the CLI version, docker compose version validates the v2 plugin registered, and docker run hello-world pulls a minimal image and runs it to close the full loop. If the last one fails but the first two succeed, the problem is usually DNS or the registry, not the install.

The next step — adding your user to the docker group with usermod -aG docker $USER and refreshing via newgrp docker — looks cosmetic but carries serious security implications. Group membership is practically equivalent to root on that machine: anyone who can run docker run can mount the root filesystem inside a privileged container. On a shared server it pays to evaluate rootless Docker, accepting its current networking limitations. On a personal box the group is acceptable if you know what you are signing up for.

Configuration That Prevents Surprises

The file /etc/docker/daemon.json is empty by default, and leaving it that way is the first production mistake almost everyone makes. Two parameters deserve to be set from day one. The first is log rotation: without a log-driver configured with max-size and max-file, a chatty container can fill the disk in a matter of days, and you usually diagnose it through a service that starts failing for no obvious reason. Ten megabytes per file and three files per container is a reasonable starting point for most workloads.

The second is live-restore, which lets running containers survive a daemon restart. That option turns Docker upgrades from a planned event into a routine operation, because systemctl reload docker or even a restart stops taking services down. Applying the changes requires systemctl reload docker after editing the file.

Problems That Always Show Up

A handful of errors recur. The permission denied when invoking docker without sudo usually comes from the group change not having been applied to the session — newgrp docker fixes it. Cannot connect to the Docker daemon points at dockerd not running, and systemctl status docker with journalctl -u docker -n 100 exposes the cause. Slow pulls are typically Docker Hub rate limits or DNS issues; a local registry-mirrors is the remedy. When disk fills up, docker system prune -a --volumes frees space aggressively, with the caveat that it also removes anonymous volumes.

My Take

Installing Docker on Debian 12 is one of those processes where the easy path — the distribution package — works well enough that you do not notice the cost until it is too late. I have migrated too many servers from docker.io to the official branch to recommend anything else: the maintenance gap pays for itself the first time a critical CVE hits the official repo on a Tuesday and Debian stable the following Friday.

What separates a viable install from one that will bite you in six months is not any command in the official repo, but the two or three decisions you make right after. Configuring log rotation from day one avoids the classic full-disk-on-vacation. Enabling live-restore turns upgrades into non-events. Understanding what the docker group implies prevents stumbling into an attack surface. None of these shows up in five-minute tutorials, and all matter more than the order in which the packages land.

The operational takeaway is simple: treat the install as a one-hour investment, not a ten-minute one. Write down in a README which decisions you made and why, because a year from now you will thank yourself for having noted that the log limit is intentional and that live-restore is on by design. The docker run hello-world that prints the green message is the beginning, not the end.

Entradas relacionadas